/**
 * Copyright(C) 2012 
 * 版权所有(C)2012 
 * <p>
 * Compiler: JDK1.6.0
 * <p>
 * 版本:  1.0版
 * 文件名：CollectionsUtils.java
 * <p>
 * 作者: hu_hengjiu
 * <p>
 * 创建时间: 2012-3-30
 * <p>
 * 负责人: hu_hengjiu
 * <p>
 * 修改者：hu_hengjiu（修改者姓名）,修改时间：2012-3-30
 * <p>
 */
package com.free.tools;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import com.free.commons.form.DynamicForm;

/**
 * 集合工具类，处理不同数据存储对象数据拷贝
 *
 */
public class CollectionsUtils extends BeanUtils{
	//防止外部类构造工具类对象
	private CollectionsUtils()
	{		
	}
	
	public static void copyProperties(DynamicForm source, Object target) throws BeansException
	{
		copyProperties(source, target, null, null);
	}
	
	@SuppressWarnings({ "rawtypes", "unused" })
	private static void copyProperties(DynamicForm source, Object target, Class editable, String[] ignoreProperties)
	throws BeansException
	{
		Class actualEditable = target.getClass();
		if (editable != null)
		{
			if (!editable.isInstance(target))
			{
				throw new IllegalArgumentException("target class ["
						+ target.getClass().getName()
						+ "] not assignable to Editable class ["
						+ editable.getName()
						+ "]");
			}
			actualEditable = editable;
		}
		PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
		List ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
		for (int i = 0; i < targetPds.length; i++)
		{
			PropertyDescriptor targetPd = targetPds[i];
			if (targetPd != null && targetPd.getWriteMethod() != null)
			{
				try
				{
					Method writeMethod = targetPd.getWriteMethod();
					if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()))
					{
						writeMethod.setAccessible(true);
					}
					String key = writeMethod.getName();//setFieldMethod,所以key值应该是去掉set后的字符串，且把第一个字符变成小写。
					key = key.substring(3);
					key = key.substring(0, 1).toLowerCase() + key.substring(1);
					
					Object value = source.get(key);
					if (value != null)
					{
						Class<?> c = writeMethod.getParameterTypes()[0];
						if (c.getName().equals(Integer.class.getName()) || c.getName().equals(int.class.getName()))
						{
							try
							{
								int intValue = Integer.parseInt(value.toString());
								writeMethod.invoke(target, new Object[]{ intValue });
							}
							catch (Exception e) 
							{
								e.printStackTrace();
							}
							
						}
						else if (c.getName().equals(Long.class.getName()))
						{
							try
							{
								long longValue = Long.parseLong(value.toString());
								writeMethod.invoke(target, new Object[]{ longValue });
							}
							catch (Exception e) 
							{
							}
								
						}
						else if (c.getName().equals(Double.class.getName()))
						{
							try
							{
								double doubleValue = Double.parseDouble(value.toString());
								writeMethod.invoke(target, new Object[]{ doubleValue });
							}
							catch (Exception e) 
							{
							}
						}
						else if (c.getName().equals(Float.class.getName()))
						{
							try
							{
								float floatValue = Float.parseFloat(value.toString());
								writeMethod.invoke(target, new Object[]{ floatValue });
							}
							catch (Exception e) 
							{
							}
						}
						else if (c.getName().equals(java.util.Date.class.getName()))
						{
							try
							{
								java.util.Date dateValue = new java.util.Date(new Long(value.toString()));
								writeMethod.invoke(target, new Object[]{ dateValue });
							}
							catch (Exception e) 
							{
							}
						}
						else 
						{
							writeMethod.invoke(target, new Object[]{ value });
						}
					}
					
				}
				catch (Throwable ex)
				{
					throw new FatalBeanException("Could not copy properties from source to target", ex);
				}
			}
		}
	}
	
	@SuppressWarnings("unused")
	private static void copyProperties(Object source, DynamicForm target, Class<?> editable, String[] ignoreProperties)
	throws BeansException
	{
		@SuppressWarnings("rawtypes")
		Class actualEditable = source.getClass();
		if (editable != null)
		{
			if (!editable.isInstance(source))
			{
				throw new IllegalArgumentException("source class ["
						+ source.getClass().getName()
						+ "] not assignable to Editable class ["
						+ editable.getName()
						+ "]");
			}
			actualEditable = editable;
		}
		PropertyDescriptor[] sourcePds = getPropertyDescriptors(actualEditable);
		@SuppressWarnings("rawtypes")
		List ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
		
		for (int i = 0; i < sourcePds.length; i++)
		{
			PropertyDescriptor sourcePd = sourcePds[i];
			if (sourcePd != null && sourcePd.getReadMethod() != null)
			{
				try
				{
					Method readMethod = sourcePd.getReadMethod();
					if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()))
					{
						readMethod.setAccessible(true);
					}
					Object value = readMethod.invoke(source, new Object[0]);
					String key = readMethod.getName();
					
					if(key.equals("getClass"))
					{
						continue;
					}
					key = key.substring(3);
					key = key.substring(0, 1).toLowerCase() + key.substring(1);
					target.set(key, value);
				}
				catch (Throwable ex)
				{
					throw new FatalBeanException("Could not copy properties from source to target", ex);
				}
			}
		}
	}
	
	/**
	 * 实体拷贝到动态Form
	 * @param entityList	实体集合
	 * @return	动态Form集合
	 */
	public static List<DynamicForm> copyToDynamicForm(List<? extends Object> entityList)
	{
		List<DynamicForm> result = new ArrayList<DynamicForm>();
		for(Object entity : entityList)
		{
			DynamicForm dynamicForm = new DynamicForm();
			copyProperties(entity, dynamicForm, null, null);
			result.add(dynamicForm);
		}
		return result;		
	}
}
